/**
 *  test_core.c - Test codes for core functions.
 *                It runs on Windows or Linux.
 *
 *  Copyright (C) 2008  ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>

#include "test_core.h"
#include "include/list.h"
#include "include/core.h"
#include "core_stubs.h"
#include "kernel/list.c"
#include "kernel/core.c"


static tcb_t tcb_array[MAX_PRIO];



static void init(void) {
    uword_t i = 0;

    is_lock_schedule = ((bool_t)FALSE);
    idle_cnt = 0;
    pcurtcb = NULL;
    pnewtcb = NULL;
    pglobal = NULL;
    highprio = 0;
    sysclock = 0;
    psleep.next = &psleep;
    psleep.prev = &psleep;
    pdelay.next = &pdelay;
    pdelay.prev = &pdelay;

    for(i = 0; i < MAX_PRIO; i++) {
        ptask[i].next = &ptask[i];
        ptask[i].prev = &ptask[i];
    }

    prio_rdy_grup = 0;
    for(i = 0; i < READY_NUM; i++) {
        prio_rdy[i] = 0;
    }

    task.next = &task;
    task.prev = &task;
}



static void test_add_tcb_rdy_0(void) {
    int i = 0;

    /* Initializing argument 1 (ptcb) */
    tcb_t *_ptcb = 0;

    /* Tested function call */
    add_tcb_rdy(_ptcb);

    for(i=0; i<MAX_PRIO; i++) {
        CU_ASSERT_PTR_EQUAL(ptask[i].prev, &ptask[i]);
    }
}



static void test_add_tcb_rdy_1(void) {
    /* Initializing argument 1 (ptcb) */
    struct task_ctrl_blk _ptcb_0 = {0};
    tcb_t *_ptcb = &_ptcb_0;
    _ptcb->prio = 34;

    /* Tested function call */
    add_tcb_rdy(_ptcb);
    CU_ASSERT_PTR_EQUAL(ptask[_ptcb->prio].prev, &_ptcb->link);
    CU_ASSERT_EQUAL(prio_rdy[_ptcb->prio >> 3], 0x4);
    CU_ASSERT_EQUAL(prio_rdy_grup, 0x10);
}



static void test_del_tcb_rdy_0(void) {
    /* Initializing argument 1 (ptcb) */
    tcb_t *_ptcb = 0;

    /* Tested function call */
    list_t *_result = del_tcb_rdy(_ptcb);

    CU_ASSERT_PTR_NULL(_result);
}



static void test_del_tcb_rdy_1(void) {
    list_t *_result = 0;

    /* Initializing argument 1 (ptcb) */
    struct task_ctrl_blk _ptcb_0 = {0};
    tcb_t *_ptcb = &_ptcb_0;
    _ptcb->prio = 34;

    add_tcb_rdy(_ptcb);

    /* Tested function call */
    _result = del_tcb_rdy(_ptcb);

    CU_ASSERT_PTR_EQUAL(_result, &_ptcb->link);
}



static void test_add_tcb_sleep_0(void) {
    /* Initializing argument 1 (ptcb) */
    tcb_t *_ptcb = 0;

    /* Tested function call */
    add_tcb_sleep(_ptcb);
    CU_ASSERT_EQUAL(psleep.next, &psleep);
}



static void test_add_tcb_sleep_1(void) {
    /* Initializing argument 1 (ptcb) */
    struct task_ctrl_blk _ptcb_0 = {0};
    tcb_t *_ptcb = &_ptcb_0;

    /* Tested function call */
    add_tcb_sleep(_ptcb);
    CU_ASSERT_EQUAL(psleep.next, &_ptcb->link);
}



static void test_chk_task_id_0(void) {
    word_t _task_id;
    bool_t _result;

    /* Reset */
    init();

    /* Initializing argument 1 (task_id) */
    _task_id = 0;

    /* Tested function call */
    _result = chk_task_id(_task_id);

    CU_ASSERT_EQUAL(_result, 1);
}



static void test_chk_task_id_1(void) {
    int i;
    bool_t _result;

    /* Initializing */
    for(i=0; i<MAX_PRIO; i++) {
        tcb_array[i].id = i;
        tcb_array[i].task_link.next = &tcb_array[i].task_link;
        tcb_array[i].task_link.prev = &tcb_array[i].task_link;
        add_node_list_rear(&task, &tcb_array[i].task_link);
    }

    for(i=0; i<MAX_PRIO; i++) {
        /* Tested function call */
        _result = chk_task_id(i);
        CU_ASSERT_EQUAL(_result, 0);
    }

    _result = chk_task_id(i);
    CU_ASSERT_EQUAL(_result, 1);
}





static void test_task(void) {

}



static void test_create_task_0(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = 0;

    /* Initializing argument 2 (pTcb) */
    tcb_t *_pTcb = 0;

    /* Initializing argument 3 (TaskID) */
    uword_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 0;

    /* Initializing argument 6 (pSpace) */
    word_t *_pSpace = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 0;

    init();

    /* Tested function call */
    _result = create_task(_pTask, _pTcb, _TaskID,
                                  _Prio, _Time, _pSpace, _StkSize);
    CU_ASSERT_EQUAL(_result, 0);
}



static void test_create_task_1(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    tcb_t *_pTcb = 0;

    /* Initializing argument 3 (TaskID) */
    uword_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 0;

    /* Initializing argument 6 (pSpace) */
    word_t *_pSpace = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 0;

    /* Tested function call */
    word_t _result = create_task(_pTask, _pTcb, _TaskID,
                                 _Prio, _Time, _pSpace, _StkSize);
    CU_ASSERT_EQUAL(_result, 0);
}



static void test_create_task_2(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    struct task_ctrl_blk tcb = {0};
    tcb_t *_pTcb = &tcb;

    /* Initializing argument 3 (TaskID) */
    uword_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time  = 0;

    /* Initializing argument 6 (pSpace) */
    word_t *_pSpace = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 0;

   /* Tested function call */
    word_t _result  = create_task(_pTask, _pTcb, _TaskID,
                                  _Prio, _Time, _pSpace, _StkSize);
    CU_ASSERT_EQUAL(_result, 0);
}



static void test_create_task_3(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    struct task_ctrl_blk tcb = {0};
    tcb_t *_pTcb = &tcb;

    /* Initializing argument 3 (TaskID) */
    uword_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = MAX_PRIO;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 0;

    /* Initializing argument 6 (pSpace) */
    word_t *_pSpace = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 1;

    /* Tested function call */
    word_t _result = create_task(_pTask, _pTcb, _TaskID,
                                 _Prio, _Time, _pSpace, _StkSize);
    CU_ASSERT_EQUAL(_result, 0);
}



static void test_create_task_4(void) {
    word_t stk[64];

    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    struct task_ctrl_blk tcb = {0};
    tcb_t *_pTcb = &tcb;

    /* Initializing argument 3 (TaskID) */
    uword_t _TaskID = 10;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = MAX_PRIO - 1;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 10;

    /* Initializing argument 6 (pSpace) */

    word_t *_pSpace = stk;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 64;

    /* Tested function call */
    word_t _result = create_task(_pTask, _pTcb, _TaskID,
                                 _Prio, _Time, _pSpace, _StkSize);
    CU_ASSERT_EQUAL(_result, 1);

    init();
}



static void test_osInitTask_0(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = 0;

    /* Initializing argument 2 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 3 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 4 (Time) */
    uword_t _Time = 0;

    /* Initializing argument 5 (StkSize) */
    uword_t _StkSize = 0;

    /* Tested function call */
    osInitTask(_pTask, _TaskID, _Prio, _Time, _StkSize);

    CU_ASSERT_PTR_EQUAL(task.next, &task);
}



static void test_osInitTask_1(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask )() = test_task;

    /* Initializing argument 2 (TaskID) */
    word_t _TaskID  = 4;

    /* Initializing argument 3 (Prio) */
    uword_t _Prio  = 0;

    /* Initializing argument 4 (Time) */
    uword_t _Time  = 1;

    /* Initializing argument 5 (StkSize) */
    uword_t _StkSize  = 0;

    /* Tested function call */
    osInitTask(_pTask, _TaskID, _Prio, _Time, _StkSize);
    CU_ASSERT_PTR_EQUAL(task.next, &task);
}



static void test_osInitTask_2(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask )() = test_task;

    /* Initializing argument 2 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 3 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 4 (Time) */
    uword_t _Time = 1u;

    /* Initializing argument 5 (StkSize) */
    uword_t _StkSize = 100;

    /* Tested function call */
    osInitTask(_pTask, _TaskID, _Prio, _Time, _StkSize);

    CU_ASSERT_PTR_NOT_EQUAL(task.next, &task);
    CU_ASSERT_PTR_NOT_EQUAL(ptask[_Prio].next, &ptask[_Prio]);
}



static void test_osInitTask_3(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 3 (Prio) */
    uword_t _Prio = 10;

    /* Initializing argument 4 (Time) */
    uword_t _Time = 1;

    /* Initializing argument 5 (StkSize) */
    uword_t _StkSize = 100;

    /* Tested function call */
    osInitTask(_pTask, _TaskID, _Prio, _Time, _StkSize);
    CU_ASSERT_PTR_EQUAL(ptask[_Prio].next, &ptask[_Prio]);
}



static void test_osCreateTask_0(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = 0;

    /* Initializing argument 2 (pTcb) */
    tcb_t *_pTcb = 0;

    /* Initializing argument 3 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 0;

    /* Initializing argument 6 (pStk) */
    word_t *_pStk = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 0;

    init();

    /* Tested function call */
    osCreateTask(_pTask, _pTcb, _TaskID, _Prio, _Time, _pStk, _StkSize);

    CU_ASSERT_PTR_EQUAL(task.next, &task);
    CU_ASSERT_PTR_EQUAL(ptask[_Prio].next, &ptask[_Prio]);
}



static void test_osCreateTask_1(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    tcb_t *_pTcb = 0;

    /* Initializing argument 3 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 0;

    /* Initializing argument 6 (pStk) */
    word_t *_pStk = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 0;

    /* Tested function call */
    osCreateTask(_pTask, _pTcb, _TaskID, _Prio, _Time, _pStk, _StkSize);

    CU_ASSERT_PTR_EQUAL(task.next, &task);
    CU_ASSERT_PTR_EQUAL(ptask[_Prio].next, &ptask[_Prio]);
}



static void test_osCreateTask_2(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    tcb_t _pTcb;

    /* Initializing argument 3 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 0;

    /* Initializing argument 6 (pStk) */
    word_t *_pStk = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 0;

    /* Tested function call */
    osCreateTask(_pTask, &_pTcb, _TaskID, _Prio, _Time, _pStk, _StkSize);

    CU_ASSERT_PTR_EQUAL(task.next, &task);
    CU_ASSERT_PTR_EQUAL(ptask[_Prio].next, &ptask[_Prio]);
}



static void test_osCreateTask_3(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    tcb_t _pTcb;

    /* Initializing argument 3 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 1;

    /* Initializing argument 6 (pStk) */
    word_t *_pStk = 0;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 0;

    /* Tested function call */
    osCreateTask(_pTask, &_pTcb, _TaskID, _Prio, _Time, _pStk, _StkSize);

    CU_ASSERT_PTR_EQUAL(task.next, &task);
    CU_ASSERT_PTR_EQUAL(ptask[_Prio].next, &ptask[_Prio]);
}



static void test_osCreateTask_4(void) {
    /* Initializing argument 1 (pTask) */
    void (*_pTask)() = test_task;

    /* Initializing argument 2 (pTcb) */
    tcb_t _pTcb;

    /* Initializing argument 3 (TaskID) */
    word_t _TaskID = 0;

    /* Initializing argument 4 (Prio) */
    uword_t _Prio = 0;

    /* Initializing argument 5 (Time) */
    uword_t _Time = 1;

    /* Initializing argument 6 (pStk) */
    word_t _pStk;

    /* Initializing argument 7 (StkSize) */
    uword_t _StkSize = 1;

    /* Tested function call */
    osCreateTask(_pTask, &_pTcb, _TaskID, _Prio, _Time, &_pStk, _StkSize);

    CU_ASSERT_PTR_EQUAL(task.next, &_pTcb.task_link);
    CU_ASSERT_PTR_EQUAL(ptask[_Prio].next, &_pTcb.link);
}



static void test_osChgPrio_0(void) {
    tcb_t tcb;
    uword_t _OldPrio = 45;

    /* Initializing argument 1 (NewPrio) */
    uword_t _NewPrio = MAX_PRIO;

    tcb.id = 10;
    tcb.prio = _OldPrio;
    tcb.link.next = &tcb.link;
    tcb.link.prev = &tcb.link;

    add_tcb_rdy(&tcb);
    pcurtcb = &tcb;

    /* Tested function call */
    osChgPrio(_NewPrio);

    CU_ASSERT_EQUAL(tcb.prio, _OldPrio);
    CU_ASSERT_PTR_EQUAL(ptask[_OldPrio].next, &tcb.link);
}



static void test_osChgPrio_1(void) {
    tcb_t tcb;
    uword_t _OldPrio = 45;

    /* Initializing argument 1 (NewPrio) */
    uword_t _NewPrio = MAX_PRIO - 1;

    tcb.id = 10;
    tcb.prio = _OldPrio;
    tcb.link.next = &tcb.link;
    tcb.link.prev = &tcb.link;

    add_tcb_rdy(&tcb);
    pcurtcb = &tcb;

    /* Tested function call */
    osChgPrio(_NewPrio);

    CU_ASSERT_EQUAL(tcb.prio, _NewPrio);
    CU_ASSERT_PTR_EQUAL(ptask[_NewPrio].next, &tcb.link);
    CU_ASSERT_PTR_EQUAL(ptask[_OldPrio].next, &ptask[_OldPrio]);
}



static void test_osKill_0(void) {
    int i;

    init();

    /* Initializing */
    for(i=0; i<MAX_PRIO; i++) {
        tcb_array[i].id = i;
        tcb_array[i].prio = i;
        tcb_array[i].link.next = &tcb_array[i].link;
        tcb_array[i].link.prev = &tcb_array[i].link;
        tcb_array[i].task_link.next = &tcb_array[i].task_link;
        tcb_array[i].task_link.prev = &tcb_array[i].task_link;

        add_tcb_rdy(&tcb_array[i]);
        add_node_list_rear(&task, &tcb_array[i].task_link);
    }


    for(i=0; i<MAX_PRIO; i++) {
        pcurtcb = &tcb_array[i];

        /* Tested function call */
        osKill();
        CU_ASSERT_PTR_NULL(pcurtcb);
        CU_ASSERT_PTR_EQUAL(ptask[i].next, &ptask[i]);
    }

    CU_ASSERT_PTR_EQUAL(task.next, &task);
}



static void test_osSleep_0(void) {
    int i;

    init();

    /* Initializing */
    for(i=0; i<MAX_PRIO; i++) {
        tcb_array[i].id = i;
        tcb_array[i].prio = i;
        tcb_array[i].link.next = &tcb_array[i].link;
        tcb_array[i].link.prev = &tcb_array[i].link;
        tcb_array[i].task_link.next = &tcb_array[i].task_link;
        tcb_array[i].task_link.prev = &tcb_array[i].task_link;

        add_tcb_rdy(&tcb_array[i]);
        add_node_list_rear(&task, &tcb_array[i].task_link);
        CU_ASSERT_PTR_EQUAL(task.prev, &tcb_array[i].task_link);
    }


    for(i=0; i<MAX_PRIO; i++) {
        pcurtcb = &tcb_array[i];

        /* Tested function call */
        osSleep();

        CU_ASSERT_EQUAL(pcurtcb->status, T_SLEEP);
        CU_ASSERT_PTR_EQUAL(ptask[i].next, &ptask[i]);
        CU_ASSERT_PTR_EQUAL(psleep.prev, &tcb_array[i].link);
    }
}



static void test_osWakeUp_0(void) {
    int i;

    for(i=0; i<MAX_PRIO; i++) {
        /* Tested function call */
        osWakeUp(i);

        CU_ASSERT_EQUAL(tcb_array[i].status, T_READY);
        CU_ASSERT_PTR_EQUAL(ptask[i].next, &tcb_array[i].link);
    }

    CU_ASSERT_PTR_EQUAL(psleep.next, &psleep);
    CU_ASSERT_PTR_EQUAL(psleep.prev, &psleep);
}




static void test_osWait_0(void) {
    int i;

    init();

    /* Initializing */
    for(i=0; i<MAX_PRIO; i++) {
        tcb_array[i].id = i;
        tcb_array[i].prio = i;
        tcb_array[i].link.next = &tcb_array[i].link;
        tcb_array[i].link.prev = &tcb_array[i].link;
        tcb_array[i].task_link.next = &tcb_array[i].task_link;
        tcb_array[i].task_link.prev = &tcb_array[i].task_link;

        add_tcb_rdy(&tcb_array[i]);
        add_node_list_rear(&task, &tcb_array[i].task_link);
        CU_ASSERT_PTR_EQUAL(task.prev, &tcb_array[i].task_link);
    }


    for(i=0; i<MAX_PRIO; i++) {
        pcurtcb = &tcb_array[i];

        /* Tested function call */
        osWait(i + 1);

        CU_ASSERT_EQUAL(pcurtcb->status, T_DELAY);
        CU_ASSERT_PTR_EQUAL(ptask[i].next, &ptask[i]);
        CU_ASSERT_PTR_EQUAL(pdelay.prev, &tcb_array[i].link);
    }
}



int test_core_init(void) {
    init();
    printf("Core test ...\n\n");
    return 0;
}



int test_core_clean(void) {
    printf("Core test is over!\n\n");
    return 0;
}



CU_TestInfo test_core_cases[] = {
    {"test_add_tcb_rdy_0", test_add_tcb_rdy_0},
    {"test_add_tcb_rdy_1", test_add_tcb_rdy_1},
    {"test_del_tcb_rdy_0", test_del_tcb_rdy_0},
    {"test_del_tcb_rdy_1", test_del_tcb_rdy_1},
    {"test_add_tcb_sleep_0", test_add_tcb_sleep_0},
    {"test_add_tcb_sleep_1", test_add_tcb_sleep_1},
    {"test_chk_task_id_0", test_chk_task_id_0},
    {"test_chk_task_id_1", test_chk_task_id_1},
    {"test_create_task_0", test_create_task_0},
    {"test_create_task_1", test_create_task_1},
    {"test_create_task_2", test_create_task_2},
    {"test_create_task_3", test_create_task_3},
    {"test_create_task_4", test_create_task_4},
    {"test_osInitTask_0", test_osInitTask_0},
    {"test_osInitTask_1", test_osInitTask_1},
    {"test_osInitTask_2", test_osInitTask_2},
    {"test_osInitTask_3", test_osInitTask_3},
    {"test_osCreateTask_0", test_osCreateTask_0},
    {"test_osCreateTask_1", test_osCreateTask_1},
    {"test_osCreateTask_2", test_osCreateTask_2},
    {"test_osCreateTask_3", test_osCreateTask_3},
    {"test_osCreateTask_4", test_osCreateTask_4},
    {"test_osChgPrio_0", test_osChgPrio_0},
    {"test_osChgPrio_1", test_osChgPrio_1},
    {"test_osKill_0", test_osKill_0},
    {"test_osSleep_0", test_osSleep_0},
    {"test_osWakeUp_0", test_osWakeUp_0},
    {"test_osWait_0", test_osWait_0},
    CU_TEST_INFO_NULL
};
